package com.xmlit.project.server;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.mortbay.log.Log;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSOutput;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.SAXException;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import com.xmlit.project.client.ExampleContainer;
import com.xmlit.project.client.UnmarshalException;
import com.xmlit.project.client.UnmarshelService;
import com.xmlit.project.engine.Utils;
import com.xmlit.project.engine.marshal.MarshalImpl;
import com.xmlit.project.engine.marshal.Unmarshal;
import com.xmlit.project.engine.marshal.UnmarshalImpl;
import com.xmlit.project.engine.struct.Struct;
import com.xmlit.project.engine.struct.impl.StructSequenceImpl;
import com.xmlit.project.engine.test.ExampleTest;
import com.xmlit.project.engine.xsd.Struct2XSD;
import com.xmlit.project.engine.xsd.XSD2Struct;

public class UnmarshelServiceImpl extends RemoteServiceServlet implements
		UnmarshelService {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
    private static final Logger log = Logger.getLogger(UnmarshelServiceImpl.class.getName());


	@Override
	public String unmarshel(String message, Struct struct)
			throws UnmarshalException {
		HttpServletRequest request = this.getThreadLocalRequest();		
		sendMail(message, "unmarshel:"+request.getRemoteAddr() + " " + request.getRemoteUser());
		message = message.replaceAll("\r\n", "\n");
		message = message.replaceAll("\n", "\r\n");
		message = Utils.dom2String(new UnmarshalImpl().unmarshal(message, struct));
		if (message.trim().indexOf('\n') == -1) {
			throw new RuntimeException("Unmarshal Failed");
		}

		return message;
	}

	/*
	 * public static String dom2String1(Document doc) {
	 * DOMImplementationRegistry registry; try { registry =
	 * DOMImplementationRegistry.newInstance(); } catch (Exception e) { throw
	 * new RuntimeException(e); }
	 * 
	 * DOMImplementationLS impl = (DOMImplementationLS) registry
	 * .getDOMImplementation("LS");
	 * 
	 * LSSerializer writer = impl.createLSSerializer();
	 * writer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
	 * LSOutput lsOutput = writer.getDomConfig().createLSOutput();
	 * .createLSOutput(); lsOutput.setEncoding("UTF-8"); String str =
	 * writer.writeToString(doc);
	 * 
	 * return str;
	 * 
	 * }
	 */


	@Override
	public String marshel(String xml, Struct struct) {
		HttpServletRequest request = this.getThreadLocalRequest();		
		sendMail(xml, "marshel:"+request.getRemoteAddr() + " " + request.getRemoteUser());

		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
			Document doc = db.parse(new ByteArrayInputStream(xml
					.getBytes("UTF-8")));
			return new MarshalImpl().marshal(doc, struct);

		} catch (Exception e) {
			throw new RuntimeException(xml, e);
		}

	}

	public static void main(String[] args) {
		String xml = "<?xml version=\"1.0\" encoding=\"UTF-16\"?><Root>   <NewElement>aaa</NewElement>   <NewElement>bbb</NewElement></Root>";
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db;
		try {
			db = dbf.newDocumentBuilder();
			Document doc = db.parse(new ByteArrayInputStream(xml
					.getBytes("UTF-16")));
			// return new MarshalImpl().marshal(doc, struct);
			System.out.println(doc);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	@Override
	public String getXSD(Struct struct) {
		return Struct2XSD.struct2XSD(struct);
	}

	@Override
	public Struct getStruct(String xsd) {
		try {
			return XSD2Struct.xsd2Struct(xsd);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	@Override
	public ExampleContainer getExampleContainer(int index) {
		StringBuffer sb;
		try {
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					this.getClass().getResourceAsStream(
							"/com/xmlit/project/examples/example" + index
									+ ".txt")));
			String line = null;
			sb = new StringBuffer();
			while (null != (line = reader.readLine())) {
				sb.append(line + "\r\n");
			}

			BufferedReader xsdReader = new BufferedReader(
					new InputStreamReader(this.getClass().getResourceAsStream(
							"/com/xmlit/project/examples/example" + index
									+ ".xsd"), "UTF-8"));
			ExampleContainer result = new ExampleContainer(
					XSD2Struct.xsd2Struct(xsdReader), sb.toString().substring(
							0, sb.length() - 2));
			return result;
		} catch (Exception e) {
			/*final char[] buffer = new char[0x10000];
			StringBuilder out = new StringBuilder();
	
			int read;
			do {
			  read = schema.read(buffer, 0, buffer.length);
			  if (read>0) {
			    out.append(buffer, 0, read);
			  }
			} while (read>=0);			
			System.out.println(out);*/
			throw new RuntimeException(e);
		}

	}

	public static void sendMail(String text, String ip) {
		// debugString += "inSend\n";
		Properties props = new Properties();
		Session session = Session.getDefaultInstance(props, null);

		try {
			Message msg = new MimeMessage(session);
			msg.setFrom(new InternetAddress("daniel.barkan@gmail.com",
					"FreeMyText Feedback"));
			msg.addRecipient(Message.RecipientType.TO, new InternetAddress(
					"yaron.galili@gmail.com", "Mr. User"));

			msg.setSubject("XML-it! monitor " + ip);
			msg.setText(text);
			Transport.send(msg);

		} catch (Exception e) {
			log.log(Level.WARNING, "mail", e);
		}

	}

	@Override
	public String ping() {
		HttpServletRequest request = this.getThreadLocalRequest();		
		sendMail("aaa", "login:"+request.getRemoteAddr() + " " + request.getRemoteUser());
		return null;
	}

}
